export function max(...args: number[]): number {
  if (args == null || !args.length) return Number.MIN_VALUE
  let maxVal = Number.MIN_VALUE
  for (const arg of args) {
    if (Array.isArray(arg)) {
      for (const e of arg) {
        if (maxVal < e) maxVal = e
      }
    } else {
      if (maxVal < arg) maxVal = arg
    }
  }
  return maxVal
}

export function maxIndexOfBy(objArray: any[], mapFn: (element: any) => any): number {
  if (objArray == null || !objArray.length) return -1
  let maxIndex = 0
  let maxVal = mapFn(maxIndex)
  for (let i = 1; i < objArray.length; i++) {
    const obj = objArray[i]
    const objVal = mapFn(obj)
    if (maxVal < objVal) {
      maxIndex = i
      maxVal = objVal
    }
  }
  return maxIndex
}

export function maxBy(objArray: any[], mapFn: (element: any) => any): any {
  const maxIndex = maxIndexOfBy(objArray, mapFn)
  if (maxIndex === -1) return undefined
  else return objArray[maxIndex]
}

export function min(...args: number[]): number {
  if (args == null || !args.length) return Number.MAX_VALUE
  let minVal = Number.MAX_VALUE
  for (const arg of args) {
    if (Array.isArray(arg)) {
      for (const e of arg) {
        if (minVal > e) minVal = e
      }
    } else {
      if (minVal > arg) minVal = arg
    }
  }
  return minVal
}

export function minIndexOfBy(objArray: any[], mapFn: (element: any) => any): number {
  if (objArray == null || !objArray.length) return -1
  let maxIndex = 0
  let maxVal = mapFn(maxIndex)
  for (let i = 1; i < objArray.length; i++) {
    const obj = objArray[i]
    const objVal = mapFn(obj)
    if (maxVal > objVal) {
      maxIndex = i
      maxVal = objVal
    }
  }
  return maxIndex
}

export function minBy(objArray: any[], mapFn: (element: any) => any): any {
  const maxIndex = minIndexOfBy(objArray, mapFn)
  if (maxIndex === -1) return undefined
  else return objArray[maxIndex]
}

